package problems;

import interfaces.EulerProblemInterface;

import java.util.LinkedList;
import java.util.List;

import utility.ListIndexHelper;
import utility.PalindromeChecker;
import utility.ProblemSpecifics;

public class EulerProblem004 implements EulerProblemInterface {

	private ProblemSpecifics problemSpecifics;
	private List<Integer> listOfPalindromes;
	private static final int BIGGEST_3_DIGIT_NUMBER = 999;
	private static final int SMALLES_3_DIGIT_NUMBER = 100;

	public EulerProblem004() {
		String problemStatement = "Find the largest palindrome made from the product of two 3-digit numbers.";
		problemSpecifics = new ProblemSpecifics(problemStatement);
		listOfPalindromes = new LinkedList<Integer>();
	}

	public void solve() {

		generateAllPossiblePalindromesAndAddToList();
		checkForLargestPalindromeInListAndSetAsResult();

	}

	private void checkForLargestPalindromeInListAndSetAsResult() {
		long result = findBiggestIntInList(listOfPalindromes);
		saveResultAndMarkSolved(result);

	}

	private void saveResultAndMarkSolved(long result) {
		problemSpecifics.setResultAndMarkSolved(result);
	}

	private void generateAllPossiblePalindromesAndAddToList() {

		for (int firstFactor = BIGGEST_3_DIGIT_NUMBER; firstFactor >= SMALLES_3_DIGIT_NUMBER; firstFactor--) {
			loopOverSecondFactor(SMALLES_3_DIGIT_NUMBER, firstFactor);
		}

	}

	private void loopOverSecondFactor(int smallest3DigitNumber, int firstFactor) {

		for (int secondFactor = firstFactor; secondFactor >= smallest3DigitNumber; secondFactor--) {

			int product = firstFactor * secondFactor;

			if (isPalindrome(product)) {
				listOfPalindromes.add(product);
			}
		}

	}

	private long findBiggestIntInList(List<Integer> listOfPalindromes) {

		long currentMax = 0;
		int lastListIndex = ListIndexHelper.getLastIndex(listOfPalindromes);

		for (int listIndex = 0; listIndex <= lastListIndex; listIndex++) {
			if (listOfPalindromes.get(listIndex) > currentMax) {
				currentMax = listOfPalindromes.get(listIndex);
			}
		}

		return currentMax;

	}

	public boolean isPalindrome(int product) {
		return PalindromeChecker.isPalindrome(product);
	}

	public long reportResult() {
		return problemSpecifics.reportResult();
	}

	public ProblemStatus reportStatus() {
		return new ProblemStatus(problemSpecifics.isSolved());
	}

	public String stateTheProblem() {
		return problemSpecifics.stateTheProblem();
	}

}
